using RRX.Xml.Helper;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Xml.Linq;

namespace RRX.Xml.ProjectTree
{
    public class ItemProjectTreeLoopPage : INotifyPropertyChanged, IItemProjectTree
    {

        public ItemProjectTreeLoopPage() {}


        // ---------- Properties ----------
        private string name { get; set; } = "LoopPage";
        public string Name
        {
            get => name;
            set
            {
                name = value;
                OnPropertyChanged("Name");
            }
        }


        private string sheet { get; set; } = "*A4 Default";
        public string Sheet
        {
            get => sheet;
            set
            {
                sheet = value;
                OnPropertyChanged("Sheet");
            }
        }




        // ---------- Basic ----------
        private ObservableCollection<IItemProjectTree> children { get; set; } = new ObservableCollection<IItemProjectTree>();
        public ObservableCollection<IItemProjectTree> Children
        {
            get => children;
            set
            {
                children = value;
                OnPropertyChanged("Children");
            }
        }



        // ---------- Functions ----------
        public IItemProjectTree Copy()
        {
            ItemProjectTreeLoopPage copy = new ItemProjectTreeLoopPage();
            copy.name = name;
            copy.sheet = sheet;

            return copy;
        }

        public XElement Xml()
        {
            double offset = 0;

            XElement xml = new XElement("lpg");
            xml.SetAttributeValue("nam", name);
            xml.SetAttributeValue("sht", sheet);
            xml.SetAttributeValue("prt", "1");

            foreach (IItemProjectTree item in Children)
            {
                if (item is not IItemProjectTreeLoop loopitem)
                    continue;

                XElement groupElement = loopitem.Xml();

                double groupMinX = double.MaxValue;
                double groupMaxX = double.MinValue;

                // 1. Ganze Gruppe vermessen
                foreach (XElement child in groupElement.Elements())
                {
                    XAttribute ptsAttribute = child.Attribute("pts");
                    if (ptsAttribute == null || string.IsNullOrWhiteSpace(ptsAttribute.Value))
                        continue;

                    List<Point> points = PointSerializer.Deserialize(ptsAttribute.Value);
                    if (points.Count == 0)
                        continue;

                    double minX = points.Min(p => p.X);
                    double maxX = points.Max(p => p.X);

                    if (minX < groupMinX)
                        groupMinX = minX;

                    if (maxX > groupMaxX)
                        groupMaxX = maxX;
                }

                // Falls keine Punkte gefunden wurden
                if (groupMinX == double.MaxValue || groupMaxX == double.MinValue)
                    continue;

                double groupWidth = groupMaxX - groupMinX;

                // 2. Ganze Gruppe gemeinsam verschieben
                foreach (XElement child in groupElement.Elements())
                {
                    XElement newChild = new XElement(child);

                    XAttribute ptsAttribute = newChild.Attribute("pts");
                    if (ptsAttribute != null && !string.IsNullOrWhiteSpace(ptsAttribute.Value))
                    {
                        List<Point> points = PointSerializer.Deserialize(ptsAttribute.Value);

                        for (int i = 0; i < points.Count; i++)
                        {
                            points[i] = new Point(points[i].X - groupMinX + offset, points[i].Y);
                        }

                        newChild.SetAttributeValue("pts", PointSerializer.Serialize(points));
                    }

                    xml.Add(newChild);
                }

                // 3. Offset für nächste Gruppe
                offset += groupWidth + loopitem.Offset;
            }

            return xml;
        }

        // ---------- PropertyChanged ----------
        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string name)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }
    }
}
